package com.example.android_calculator

import java.util.*

//符号优先级
//比较两个运算符的大小，如果peek优先级大于等于cur，返回true
class Caculate{
    fun compareOper(peek: String, cur: String): Boolean {
        if ("*" == peek && ("/" == cur || "*" == cur || "+" == cur || "-" == cur)) {
            return true
        } else if ("/" == peek && ("/" == cur || "*" == cur || "+" == cur || "-" == cur)) {
            return true
        } else if ("+" == peek && ("+" == cur || "-" == cur)) {
            return true
        } else if ("-" == peek && ("+" == cur || "-" == cur)) {
            return true
        }
        return false
    }

    //判断一个字符串是否是运算符，+-*/
    fun isOper(c: String): Boolean {
        if (c == "+" || c == "-" || c == "*" || c == "/")
        {
            return true;
        }else
        {
            return false
        }

    }

    //将例如1522.3的多位数字拼接

    fun pinjie(list:MutableList<Char>):MutableList<String>{

        //如果最后一个元素是操作符，则删除掉。
        if(isOper(list.last().toString()))
        {
           list.removeAt(list.size-1)
        }
        //数据的集合
        var data= mutableListOf<String>();

        //
        var num="";
        for(i in 0 until list.size)
        {

            //多位数的拼接
            if(Character.isDigit(list[i]) ||list[i]=='.')
            {
                num+=list[i];
                if(i==list.size-1)
                {
                    data.add(num)
                    num=""
                }
            }else
            {
                if(num!="")
                {
                    //上一次的数字添加到集合中
                    data.add(num)
                    num=""
                }
                data.add(list[i]+"")


            }
        }
        return data
    }

    //获取后缀表达式
//如果不是符号，直接放进表达式
//如果是符号，要看跟栈顶的符号比较优先级，当前运算符优先级>栈顶元素，当前运算符入栈。否则栈顶元素出栈，总之在符号栈中上面的符号都是高级的
    fun  getPostOrder(data:MutableList<String>):MutableList<String>
    {
        //后缀表达式
        var postOrder= mutableListOf<String>()
        //操作符的栈
        var stack = Stack<String>()

        for(i in 0 until data.size )
        {
            var s=data[i]
            if(isOper(s))
            {
                //运算符不为空并且栈顶元素大于当前的符号元素，栈顶元素出栈到后缀表达式里，
                while(!stack.isEmpty()&& compareOper(stack.peek(),s))
                {
                    postOrder.add(stack.pop())
                }
                stack.push(s)


            }else
            {
                //否则当为空时或栈顶元素小于当前符号元素或者不是字符元素，将当前元素入栈
                postOrder.add(s);
            }
        }

        //如果最后栈不为空时，全出栈到表达式去
        while(!stack.isEmpty())
        {
            postOrder.add(stack.pop())
        }

        return postOrder
    }

    //计算后缀表达式
    fun calculate(postOrder:MutableList<String>):Double{
        var stack=Stack<String>()
        for(i in 0 until postOrder.size)
        {
            var c=postOrder[i]
            var res=1.0
            if (!isOper(c))
            {
                stack.push(c)
            }else
            {
                when(c)
                {
                    "+"->{
                        var num1=stack.pop().toDouble()
                        var num2=stack.pop().toDouble()
                        res=num1+num2
                    }
                    "-"->{
                        var num1=stack.pop().toDouble()
                        var num2=stack.pop().toDouble()
                        res=num2-num1
                    }
                    "*"->{
                        var num1=stack.pop().toDouble()
                        var num2=stack.pop().toDouble()
                        res=num1*num2
                    }
                    "/"->{
                        var num1=stack.pop().toDouble()
                        var num2=stack.pop().toDouble()
                        res=num2/num1
                    }
                }

                stack.push(res.toString())

            }

        }
        return stack.pop().toDouble()
    }

}
fun main() {
    var c=Caculate()
    val list= mutableListOf('1','3','3','.','5','-','2','/','2')
    var m= c.pinjie(list);
    var post= c.getPostOrder(m)

    println(m)
    print(post)
    print( c.calculate(post))

}
